package com.example.demo.service.Imp;

import com.alibaba.fastjson2.JSON;
import com.example.demo.entity.table.LawsContent;
import com.example.demo.entity.table.LawsList;
import com.example.demo.mapper.LawMapper;
import com.example.demo.service.LawService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.Collections;

import com.example.demo.entity.req.LawsListsReq;
import com.example.demo.entity.req.LawsDetailReq;
import com.example.demo.entity.res.LawsDetailRes;
import com.example.demo.entity.req.updateLawContentReq;
import org.springframework.web.multipart.MultipartFile;
import com.example.demo.entity.req.updateLawInfoReq;
import com.example.demo.entity.req.addLawReq;
import org.springframework.transaction.annotation.Transactional;

@Service
public class LawServiceImp implements LawService {
    private static final Logger log = LoggerFactory.getLogger(LawServiceImp.class);

    @Autowired
    private LawMapper lawMpper;

    // 定义图片保存目录
    private static final String IMAGE_SAVE_DIR = "D:/upload/";

    // 获取法规内容
    @Override
    public int oldToNew(String TableName) {
        List<LawsContent> lawContents = lawMpper.getLawTableContent(TableName);


        // 先获取所有目录内容行，然后提取CH_HTML中的href，然后再提取href中的去掉第一个字符#的内容
        List<String> chapterList = new ArrayList<>();
        for (LawsContent lawContent : lawContents) {
            if (lawContent.getTYPE().equals("目录内容")) {
                String chapter = lawContent.getCH_HTML();
                if (chapter != null && chapter.contains("href")) {
                    try {
                        // 使用正则表达式提取href中的ID，格式：<a href = "#id">内容</a>
                        Pattern pattern = Pattern.compile("href\\s*=\\s*[\"']#([^\"']+)[\"']");
                        Matcher matcher = pattern.matcher(chapter);
                        if (matcher.find()) {
                            String hrefId = matcher.group(1);
                            chapterList.add(hrefId);
                            log.debug("提取到章节ID: {}", hrefId);
                        } else {
                            log.warn("目录内容格式不匹配，无法提取href ID: {}", chapter);
                        }
                    } catch (Exception e) {
                        log.warn("解析目录内容href时发生错误，章节内容: {}, 错误: {}", chapter, e.getMessage());
                    }
                } else {
                    log.warn("目录内容中没有找到href属性: {}", chapter);
                }
            }
        }
        log.info("提取到的章节列表: {}", chapterList);





        List<String> articlesColumnList = Arrays.asList("抬头内容", "正文标题", "正文内容", "正文编号", "表格标题", "数据表格", "图片标题", "附录标题",
                "附录编号", "附录内容", "公式内容");

        List<String> centerColumnList = Arrays.asList("抬头内容", "图片标题", "表格标题", "数据表格", "附录标题", "公式内容");

        StringBuilder htmlContent = new StringBuilder();

        // 收集目录项的列表
        List<DirectoryItem> directoryList = new ArrayList<>();

        int number = 0;

        // 创建一个法规uuid
        String uuid = java.util.UUID.randomUUID().toString();

        for (LawsContent lawContent : lawContents) {
            String htmlContentItem = "";

            // 判断item.getTYPE()是否包含在articlesColumnList中;
            if (articlesColumnList.contains(lawContent.getTYPE())) {
                // 根据 PUID 是否在 chapterList 中决定使用 h4 还是 p 标签
                boolean isChapter = chapterList.contains(lawContent.getPUID());
                boolean isCenter = centerColumnList.contains(lawContent.getTYPE());
                
                if (isChapter) {
                    // 使用 h4 标签
                    if (isCenter) {
                        htmlContentItem += "<h4 id=\"" + lawContent.getPUID() + "\" style=\"text-align: center;\">"
                                + lawContent.getCH_HTML() + " " + lawContent.getCO_HTML() + "</h4>";
                    } else {
                        htmlContentItem += "<h4 id=\"" + lawContent.getPUID() + "\">" + lawContent.getCH_HTML() + " "
                                + lawContent.getCO_HTML() + "</h4>";
                    }
                } else {
                    // 使用 p 标签
                    if (isCenter) {
                        htmlContentItem += "<p id=\"" + lawContent.getPUID() + "\" style=\"text-align: center;\">" 
                                + lawContent.getCH_HTML() + " " + lawContent.getCO_HTML() + "</p>";
                    } else {
                        htmlContentItem += "<p id=\"" + lawContent.getPUID() + "\">" + lawContent.getCH_HTML() + " "
                                + lawContent.getCO_HTML() + "</p>";
                    }
                }

            }

            // 如果是图片内容需要先提取base64内容然后保存图片再把图片路径反写到HTML中
            else if (lawContent.getCO_HTML() != null && lawContent.getTYPE().equals("图片内容")) {
                htmlContentItem += "<p id=\"" + lawContent.getPUID() + "\" style=\"text-align: center;\">"
                        + lawContent.getCH_HTML() + " " + handleImages(lawContent.getCO_HTML(), uuid) + "</p>";
            }
            htmlContent.append(htmlContentItem);

            // 如果SPECIFICATION不为空，则将SPECIFICATION中的图片标签替换为真实图片地址
            if (lawContent.getSPECIFICATION() != null && !lawContent.getSPECIFICATION().equals("")) {
                // 检查SPECIFICATION内容是否包含图片标签
                String specificationContent = lawContent.getSPECIFICATION();
                if (specificationContent.contains("<img")) {
                    // 处理图片标签，将base64的src替换为真实图片地址
                    specificationContent = handleImages(specificationContent, uuid);
                }
                // 将处理后的SPECIFICATION内容追加到htmlContent中
                htmlContent.append("<blockquote>" + specificationContent + "</blockquote>");
            }

            // 目录内容
            if (lawContent.getTYPE().equals("目录内容")) {
                number++;

                DirectoryItem directoryItem = new DirectoryItem(
                        "heading" + number,
                        lawContent.getCHAPTER() + " " + lawContent.getCONTENT());

                // 将目录项添加到列表中
                directoryList.add(directoryItem);
            }

        }

        // 使用FastJSON将目录列表转换为JSON字符串
        String directoryJson = JSON.toJSONString(directoryList);

        // 将法规内容保存到新的数据表中

        try {
            // Correct the method call with a Date object
            lawMpper.insertLawsList(uuid, TableName, new Date());
            lawMpper.insertLawsDetail(uuid, directoryJson, htmlContent.toString());
        } finally {
            // Add any necessary cleanup code here
        }
        return number; // Return the number of directory items processed
    }

    // 获取法规列表
    @Override
    public List<LawsList> getLawsLists(LawsListsReq req) {
        try {
            List<LawsList> result = lawMpper.getLawsLists(req);
            return result;
        } catch (Exception e) {
            log.error("服务器错误", e);
            return null;
        }
    }

    // 更新法规内容和目录
    @Override
    @Transactional
    public int updateLawContent(updateLawContentReq req) {
        try {
            // 更新数据库内容
            lawMpper.updateLawContent(req);

            // 清理不再使用的图片文件（在数据库更新成功后）
            cleanupUnusedImages(req);

            return 1;
        } catch (Exception e) {
            log.error("更新法规详情时发生错误", e);
            throw new RuntimeException("更新法规内容失败: " + e.getMessage(), e);
        }
    }

    /**
     * 清理不再使用的图片文件
     * 只保留前端提供的imageUrls列表中的文件，其余全部删除
     */
    private void cleanupUnusedImages(updateLawContentReq req) {
        try {
            // 获取文章目录下的所有文件
            List<String> existingFiles = getAllFilesInArticleDir(req.getId());

            if (existingFiles.isEmpty()) {
                log.info("文章目录下没有文件需要清理");
                return;
            }

            // 获取前端提供的有效图片URL列表（提取文件名）
            Set<String> validFileNames = new HashSet<>();
            if (req.getImageUrls() != null && !req.getImageUrls().isEmpty()) {
                for (String imageUrl : req.getImageUrls()) {
                    String fileName = extractFileNameFromUrl(imageUrl);
                    if (fileName != null && !fileName.isEmpty()) {
                        validFileNames.add(fileName);
                    }
                }
            }

            // 找出需要删除的文件（除了有效文件外的所有文件）
            List<String> filesToDelete = existingFiles.stream()
                    .filter(fileName -> !validFileNames.contains(fileName))
                    .collect(Collectors.toList());

            // 删除不再使用的文件
            deleteAllFiles(req.getId(), filesToDelete);

            if (!filesToDelete.isEmpty()) {
                log.info("已删除 {} 个不再使用的文件: {}", filesToDelete.size(), filesToDelete);
                log.info("保留 {} 个有效文件: {}", validFileNames.size(), validFileNames);
            } else {
                log.info("没有需要删除的文件");
            }

        } catch (Exception e) {
            log.error("清理不再使用的图片文件时发生错误", e);
        }
    }

    /**
     * 获取文章目录下的所有文件名（不限制文件类型）
     */
    private List<String> getAllFilesInArticleDir(String articleId) {
        String articleDir = IMAGE_SAVE_DIR + articleId + "/";
        java.io.File directory = new java.io.File(articleDir);

        if (!directory.exists() || !directory.isDirectory()) {
            return new ArrayList<>();
        }

        String[] files = directory.list();
        if (files == null) {
            return new ArrayList<>();
        }

        // 返回所有文件，不做文件类型过滤
        return Arrays.asList(files);
    }

    /**
     * 从URL中提取文件名
     */
    private String extractFileNameFromUrl(String url) {
        if (url == null || url.isEmpty()) {
            return null;
        }

        // 如果是完整URL，提取文件名部分
        if (url.startsWith("http://localhost:8080/files/")) {
            int lastSlashIndex = url.lastIndexOf("/");
            if (lastSlashIndex != -1 && lastSlashIndex < url.length() - 1) {
                return url.substring(lastSlashIndex + 1);
            }
        }

        // 如果直接是文件名，直接返回
        return url;
    }

    /**
     * 删除指定的所有文件（不限制文件类型）
     */
    private void deleteAllFiles(String articleId, List<String> fileNames) {
        String articleDir = IMAGE_SAVE_DIR + articleId + "/";

        for (String fileName : fileNames) {
            try {
                java.io.File file = new java.io.File(articleDir + fileName);
                if (file.exists() && file.isFile()) {
                    boolean deleted = file.delete();
                    if (deleted) {
                        log.info("已删除文件: {}", file.getAbsolutePath());
                    } else {
                        log.warn("删除文件失败: {}", file.getAbsolutePath());
                    }
                }
            } catch (Exception e) {
                log.error("删除文件时发生错误: {}", fileName, e);
            }
        }
    }

    // 获取法规详情
    @Override
    public LawsDetailRes getLawDetail(LawsDetailReq req) {
        try {
            return lawMpper.getLawsDetail(req);
        } catch (Exception e) {
            log.error("获取法规详情时发生错误", e);
            return null;
        }
    }

    // 上传文件
    @Override
    public String uploadImage(MultipartFile image, String id) {
        if (image == null || image.isEmpty()) {
            throw new RuntimeException("图片文件不能为空");
        }

        try {
            // 获取文件扩展名
            String originalFilename = image.getOriginalFilename();
            String fileExtension = "png"; // 默认扩展名
            if (originalFilename != null && originalFilename.contains(".")) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            }

            // 生成唯一文件名，使用UUID确保唯一性
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String fileName = System.currentTimeMillis() + "_" + uuid + "." + fileExtension;

            // 获取文件字节数据
            byte[] fileData = image.getBytes();

            // 使用通用保存方法
            return saveFileToArticleDir(id, fileName, fileData);

        } catch (IOException e) {
            log.error("读取图片文件时发生错误: {}", e.getMessage(), e);
            throw new RuntimeException("读取图片文件失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("处理图片上传时发生错误: {}", e.getMessage(), e);
            throw new RuntimeException("图片上传失败: " + e.getMessage());
        }
    }

    /**
     * 通用的文件保存方法
     * 
     * @param articleId 文章ID
     * @param fileName  文件名
     * @param fileData  文件数据
     * @return 文件访问URL
     */
    private String saveFileToArticleDir(String articleId, String fileName, byte[] fileData) {
        String filePath = null;
        java.io.File destFile = null;

        try {
            // 创建以文章ID为名称的目录
            String articleDir = IMAGE_SAVE_DIR + articleId + "/";
            java.io.File directory = new java.io.File(articleDir);
            if (!directory.exists()) {
                boolean created = directory.mkdirs();
                if (!created) {
                    throw new RuntimeException("无法创建上传目录: " + articleDir);
                }
            }

            filePath = articleDir + fileName;
            destFile = new java.io.File(filePath);

            // 使用同步块确保文件操作的原子性
            synchronized (this) {
                // 再次检查文件是否存在
                if (destFile.exists()) {
                    throw new RuntimeException("文件名冲突，请重试");
                }

                // 保存文件
                try (FileOutputStream fos = new FileOutputStream(destFile)) {
                    fos.write(fileData);
                }
            }

            log.info("文件已成功保存至: {}", filePath);

            // 返回访问地址（包含文章ID文件夹路径）
            String accessUrl = "http://localhost:8080/files/" + articleId + "/" + fileName;
            return accessUrl;

        } catch (IOException e) {
            log.error("保存文件时发生IO错误: {}", e.getMessage(), e);
            // 如果保存失败，尝试删除可能创建的文件
            if (destFile != null && destFile.exists()) {
                try {
                    boolean deleted = destFile.delete();
                    if (deleted) {
                        log.info("已删除失败的文件: {}", filePath);
                    }
                } catch (Exception deleteEx) {
                    log.warn("删除失败文件时发生错误: {}", deleteEx.getMessage());
                }
            }
            throw new RuntimeException("保存文件失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("处理文件保存时发生错误: {}", e.getMessage(), e);
            // 如果保存失败，尝试删除可能创建的文件
            if (destFile != null && destFile.exists()) {
                try {
                    boolean deleted = destFile.delete();
                    if (deleted) {
                        log.info("已删除失败的文件: {}", filePath);
                    }
                } catch (Exception deleteEx) {
                    log.warn("删除失败文件时发生错误: {}", deleteEx.getMessage());
                }
            }
            throw new RuntimeException("文件保存失败: " + e.getMessage());
        }
    }

    // 目录类
    public static class DirectoryItem {
        public final String key;
        public final String title;
        public final List<DirectoryItem> children = new ArrayList<>();

        public DirectoryItem(String key, String title) {
            this.key = key;
            this.title = title;
        }

        public void addChild(DirectoryItem child) {
            children.add(child);
        }

    }

    // 处理图片的总函数
    private String handleImages(String imageContent, String articleId) {
        // 提取base64图片数据并保存为文件，获取文件路径
        String srcPath = extractTextFromImages(imageContent);
        String filePath = saveBase64ImageToFile(srcPath, articleId);

        // 如果保存成功，替换HTML中的base64为文件路径
        if (filePath != null && srcPath != null) {
            imageContent = imageContent.replaceAll("src\\s*=\\s*['\"]" + Pattern.quote(srcPath) + "['\"]",
                    "src=\"" + filePath + "\"");
        }

        return imageContent;
    }

    // 从HTML中的图片提取src属性内容
    private String extractTextFromImages(String html) {
        if (html == null || html.isEmpty()) {
            return "";
        }

        try {
            // 使用正则表达式匹配<img>标签中的src属性
            Pattern pattern = Pattern.compile("<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>",
                    Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(html);

            if (matcher.find()) {
                return matcher.group(1);
            }
        } catch (Exception e) {
            log.error("提取图片内容时发生错误", e);
        }
        return "";
    }

    // 将base64编码的图片保存到指定目录
    private String saveBase64ImageToFile(String base64Image, String articleId) {
        if (base64Image == null || base64Image.isEmpty()) {
            log.warn("图片数据为空，无法保存");
            return null;
        }

        // 检查是否为base64数据URI
        String base64Data = base64Image;
        String fileExtension = "png"; // 默认扩展名

        try {
            if (base64Image.startsWith("data:image/")) {
                // 提取文件类型
                String[] parts = base64Image.split(";");
                if (parts.length > 0) {
                    String mimeType = parts[0].substring(11); // 移除 "data:image/"
                    String[] mimeTypeParts = mimeType.split("/");
                    if (mimeTypeParts.length > 1) {
                        fileExtension = mimeTypeParts[1];
                    }
                }

                // 提取base64数据部分
                String[] dataParts = base64Image.split(",");
                if (dataParts.length > 1) {
                    base64Data = dataParts[1];
                }
            }

            // 生成唯一文件名
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String fileName = System.currentTimeMillis() + "_" + uuid + "." + fileExtension;

            // 清理base64数据，移除可能的非法字符
            String cleanedBase64Data = base64Data.replaceAll("\\s+", "");

            // 解码图片数据
            byte[] imageBytes = Base64.getDecoder().decode(cleanedBase64Data);

            // 使用通用保存方法
            return saveFileToArticleDir(articleId, fileName, imageBytes);

        } catch (IllegalArgumentException e) {
            log.error("Base64解码错误，数据可能不正确: {}", e.getMessage());
            log.error("原始数据前100个字符: {}", base64Data.length() > 100 ? base64Data.substring(0, 100) : base64Data);
        } catch (Exception e) {
            log.error("处理base64图片数据时发生错误", e);
        }

        return null;
    }



    // 更新法规信息
    @Override
    public int updateLawInfo(updateLawInfoReq req) {
        try {
            return lawMpper.updateLawInfo(req);
        } catch (Exception e) {
            log.error("更新法规信息时发生错误", e);
            return 0;
        }
    }

    // 新增法规
    @Override
    @Transactional
    public String addLaw(addLawReq req) {
        // 生成一个uuid
        String uuid = java.util.UUID.randomUUID().toString();
        req.setId(uuid);
        
        // 为空字段设置默认值
        if (req.getEditor() == null || req.getEditor().isEmpty()) {
            req.setEditor("admin");
        }
        if (req.getDescribe() == null) {
            req.setDescribe("");
        }
        if (req.getTags() == null) {
            req.setTags("");
        }

        try {
            // 插入到 laws_list 表（包含基础信息）
            lawMpper.addlawsList(req);
            
            // 插入到 laws_detail 表（directory 和 content 为空）
            lawMpper.addlawsDetail(req);
            
            log.info("成功新增法规，ID: {}, 标题: {}", uuid, req.getTitle());
            return uuid;  // 返回生成的ID
        } catch (Exception e) {
            log.error("新增法规时发生错误: {}", e.getMessage(), e);
            // 事务会自动回滚
            throw new RuntimeException("新增法规失败: " + e.getMessage(), e);
        }
    }


    // 删除法规
    @Override
    @Transactional
    public int deleteLaws(List<String> ids) {
        try {
            // 删除 laws_detail 表中的数据
            int detailResult = lawMpper.deleteLawsDetail(ids);
            
            // 删除 laws_list 表中的数据
            int listResult = lawMpper.deleteLaws(ids);
            
            // 删除对应的图片文件夹
            for (String id : ids) {
                deleteArticleDirectory(id);
            }
            
            log.info("成功删除法规，laws_detail: {} 条，laws_list: {} 条", detailResult, listResult);
            return listResult;
        } catch (Exception e) {
            log.error("删除法规时发生错误", e);
            throw new RuntimeException("删除法规失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 删除文章目录及其下的所有文件
     */
    private void deleteArticleDirectory(String articleId) {
        try {
            String articleDir = IMAGE_SAVE_DIR + articleId + "/";
            java.io.File directory = new java.io.File(articleDir);
            
            if (directory.exists() && directory.isDirectory()) {
                // 删除目录下的所有文件
                java.io.File[] files = directory.listFiles();
                if (files != null) {
                    for (java.io.File file : files) {
                        if (file.isFile()) {
                            boolean deleted = file.delete();
                            if (deleted) {
                                log.debug("已删除文件: {}", file.getAbsolutePath());
                            }
                        }
                    }
                }
                
                // 删除空目录
                boolean deleted = directory.delete();
                if (deleted) {
                    log.info("已删除文章目录: {}", articleDir);
                }
            }
        } catch (Exception e) {
            log.warn("删除文章目录时发生错误: {}, 错误: {}", articleId, e.getMessage());
        }
    }


    // 获取所有的法规标签
    @Override
    public List<String> getAllTags() {
        try {
            List<String> allTags = lawMpper.getAllTags();
            Set<String> uniqueTags = new HashSet<>();
            
            // 处理逗号分隔的标签
            for (String tagString : allTags) {
                if (tagString != null && !tagString.trim().isEmpty()) {
                    // 按逗号分割标签
                    String[] tags = tagString.split(",");
                    for (String tag : tags) {
                        String trimmedTag = tag.trim();
                        if (!trimmedTag.isEmpty()) {
                            uniqueTags.add(trimmedTag);
                        }
                    }
                }
            }
            
            List<String> result = new ArrayList<>(uniqueTags);
            Collections.sort(result); // 排序
            log.info("获取到 {} 个不重复的标签: {}", result.size(), result);
            return result;
        } catch (Exception e) {
            log.error("获取标签时发生错误", e);
            return new ArrayList<>();
        }
    }


}